package com.code2roc.fastface.db;

import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.code2roc.fastface.util.CommonUtil;
import com.code2roc.fastface.util.ConvertOp;
import com.code2roc.fastface.util.ReflectUtil;
import com.code2roc.fastface.util.StringUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.lang.reflect.Field;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;

@Component
public class BaseServiceImpl <T extends BaseModel> implements BaseService<T>{
    @Autowired
    public CommonDTO commonDTO;
    @Autowired
    public CommonWrapper commonWrapper;
    public String tableName;
    public String tableKeyName;
    public Class entityClass;
    public BaseMapper mapperBean;
    @Autowired
    public MapperBeanManage mapperBeanManage;

    public BaseServiceImpl() {
        entityClass = getEntityClass();
        tableName = getTableName(entityClass);
        tableKeyName = getTableKeyName(entityClass);
    }

    public void insert(T entity) {
        getMapper().insert(entity);
    }


    public void delete(String id) {
        UpdateWrapper wrapper = commonWrapper.getDeleteWrapperFillKey(entityClass, id);
        getMapper().delete(wrapper);
    }

    public void delete(String fieldName, Object filedValue) {
        UpdateWrapper wrapper = commonWrapper.getDeleteWrapperCustomKey(fieldName, filedValue);
        getMapper().delete(wrapper);
    }

    public void batchDelte(List<String> idList) {
        for (String id : idList) {
            delete(id);
        }
    }

    public void update(T entity) {
        UpdateWrapper wrapper = commonWrapper.getUpdateWrapperFillKey(entity);
        getMapper().update(entity, wrapper);
    }

    public void batchUpdate(List<T> entityList) {
        for (T entity : entityList) {
            update(entity);
        }
    }

    public void save(T entity) {
        String unitguid = "";
        if (StringUtil.isEmpty(getTableKeyValue(entity))) {
            unitguid = CommonUtil.getNewGuid();
            setTableKeyValue(entity,unitguid);
        } else {
            unitguid = getTableKeyValue(entity);
        }
        if (null == selectOne(unitguid)) {
            insert(entity);
        } else {
            update(entity);
        }
    }

    public T selectOne(String unitguid) {
        return (T) commonDTO.selectOne(entityClass, tableName, "*", tableKeyName, unitguid);
    }

    public Page selectPage(String columns, String where, String orderBy, HashMap<String, Object> paramMap) {
        return commonDTO.selectPage(tableName, columns, where, orderBy, paramMap);
    }

    public List<T> selectPageList(String columns, String where, String orderBy, HashMap<String, Object> paramMap) {
        return (List<T>) commonDTO.selectPageList(entityClass, tableName, columns, where, orderBy, paramMap);
    }

    public List<T> selectList(String columns, String where, String orderBy, HashMap<String, Object> paramMap) {
        return (List<T>) commonDTO.selectList(entityClass, tableName, columns, where, orderBy, paramMap);
    }

    @Override
    public List<T> selectAllList() {
        return (List<T>) commonDTO.selectList(entityClass, tableName, "*", "1=1", "", new HashMap<>());
    }

    @Override
    public List<T> selectListByField(String filedName, Object filedValue) {
        String sql = filedName + " = #{" + filedName + "}";
        HashMap paramMap = new HashMap();
        paramMap.put(filedName, filedValue);
        return selectList("*", sql, "", paramMap);
    }

    @Override
    public List<T> selectRangeList(List<String> rowIDList) {
        String rowIDString = "";
        if (rowIDList.size() == 0) {
            rowIDString = "''";
        } else {
            for (int i = 0; i < rowIDList.size(); i++) {
                if (!rowIDString.contains(rowIDList.get(i))) {
                    if (i == rowIDList.size() - 1) {
                        rowIDString += "'" + rowIDList.get(i) + "'";
                    } else {
                        rowIDString += "'" + rowIDList.get(i) + "',";
                    }
                }
            }
        }
        String sql = "  "+tableKeyName+" in (" + rowIDString + ") ";
        return selectList("*", sql, "", null);
    }


    @Override
    public List<T> selectRangeListByField(String filedName, List<String> rowIDList) {
        String rowIDString = "";
        if (rowIDList.size() == 0) {
            rowIDString = "''";
        } else {
            for (int i = 0; i < rowIDList.size(); i++) {
                if (!rowIDString.contains(rowIDList.get(i))) {
                    if (i == rowIDList.size() - 1) {
                        rowIDString += "'" + rowIDList.get(i) + "'";
                    } else {
                        rowIDString += "'" + rowIDList.get(i) + "',";
                    }
                }
            }
        }
        String sql = "  " + filedName + " in (" + rowIDString + ") ";
        return selectList("*", sql, "", null);
    }

    @Override
    public boolean checkExist(String fieldName, Object fieldValue) {
        String sql = " " + fieldName + "= #{" + fieldName + "}";
        HashMap paramMap = new HashMap();
        paramMap.put(fieldName, fieldValue);
        return selectCount(sql, paramMap) > 0;
    }

    @Override
    public boolean checkExist(String fieldName, Object fieldValue, String rowID) {
        String sql = " " + fieldName + "= #{" + fieldName + "} and "+tableKeyName+" != #{row_id}";
        HashMap paramMap = new HashMap();
        paramMap.put(fieldName, fieldValue);
        paramMap.put("row_id", tableKeyName);
        return selectCount(sql, paramMap) > 0;
    }

    public int selectCount(String where, HashMap<String, Object> paramMap) {
        return commonDTO.selectCount(tableName, where, paramMap);
    }

    @Override
    public T selectOneByField(String fieldName, Object filedValue) {
        return (T) this.commonDTO.selectOne(this.entityClass, this.tableName, "*", fieldName, filedValue.toString());
    }

    @Override
    public void deleteByField(String fieldName, Object filedValue) {
        UpdateWrapper wrapper = this.commonWrapper.getDeleteWrapperCustomKey(fieldName, filedValue);
        this.getMapper().delete(wrapper);
    }

    @Override
    public void deleteAll() {
        String sql = "delete from " + tableName;
        commonDTO.executeSQL(sql, null);
    }

    //获取泛型具体对应class
    public Class getEntityClass() {
        return ReflectUtil.getSuperClassGenricType(this.getClass());
    }

    //获取表名
    public String getTableName(Class<T> clazz) {
        String tabaleName = "";
        TableName tableNameAnnotaion = (TableName) clazz.getAnnotation(TableName.class);
        if (tableNameAnnotaion != null) {
            tabaleName = tableNameAnnotaion.value();
        }
        if ("".equals(tabaleName)) {
            tabaleName = clazz.getSimpleName();
        }
        return tabaleName;
    }

    //获取主键名称
    public String getTableKeyName(Class<T> clazz) {
        String tableKeyName = "";
        List<Field> fs = Arrays.asList(clazz.getDeclaredFields());
        for (Field field : fs) {
            field.setAccessible(true);
            //TableId修饰主键
            TableId tableIDAnnotaion = field.getAnnotation(TableId.class);
            if (tableIDAnnotaion != null) {
                tableKeyName = tableIDAnnotaion.value();
                break;
            }
        }
        if ("".equals(tableKeyName)) {
            tableKeyName = "id";
        }
        return tableKeyName;
    }

    public String getTableKeyValue(T entity) {
        String tableKeyValue = "";
        List<Field> fs = Arrays.asList(entityClass.getDeclaredFields());
        for (Field field : fs) {
            field.setAccessible(true);
            //TableId修饰主键
            TableId tableIDAnnotaion = field.getAnnotation(TableId.class);
            if (tableIDAnnotaion != null) {
                try{
                    tableKeyValue = ConvertOp.convert2String(field.get(entity));
                }catch (Exception e){
                    e.printStackTrace();
                }
                break;
            }
        }
        return tableKeyValue;
    }

    public void setTableKeyValue(T entity, String value){
        List<Field> fs = Arrays.asList(entityClass.getDeclaredFields());
        for (Field field : fs) {
            field.setAccessible(true);
            //TableId修饰主键
            TableId tableIDAnnotaion = field.getAnnotation(TableId.class);
            if (tableIDAnnotaion != null) {
                try{
                    field.set(entity,value);
                }catch (Exception e){
                    e.printStackTrace();
                }
                break;
            }
        }
    }

    //获取Dao对应的bean
    public BaseMapper getMapper() {
        if (null == mapperBean) {
            String tableNameValue = StringUtil.replaceLast(entityClass.getSimpleName().toLowerCase(),"do","");
            mapperBean = mapperBeanManage.getMapper(tableNameValue);
        }
        return mapperBean;
    }
}
